$("head").append('<style>[data-if],[data-elif],[data-else],[data-for],[data-each]{display: none;}' +
    '@keyframes myopacity{from {opacity:0;}to {opacity:1;}}' +
    '@-webkit-keyframes myopacity{from {opacity:0;}to {opacity:1;}}</style>');


(function($){

    var opt = {
        useCatch:false,
        version:"1.0.0",
        scroll:{
            page:"page",//当前页数的Key
            size:"size",//每页条数数的Key
            param:[]//cookie里的数据，在请求接口会加上去
        }
    };
    var fragment;//body内容，只有一个
    var fragmentClone;
    var prefix = "data-";//标签前缀,用户可以自行修改
    var plugs = ["layout", "go"];
    var placeholderThat = $("<div></div>");
    //页面数据
    var initPage = true;
    var pageDataInit = {search:{}, hash:{}, cookie:{}, window:{}};
    var pageData = {search:{}, hash:{}, cookie:{}, window:{}};
    var goState = false;//是否支持返回事件
    var scroll;

    //按规则解析url的参数
    var urlParam = function (url, reg) {
        var paramData = {};
        if(url){
            var params = url.split(reg)
            if(params){
                for(var i=0;i<params.length;i++){
                    var k = params[i].split("=")[0];
                    var v = params[i].replace(k+"=", "");
                    if(k){
                        k = k.trim();
                    }
                    paramData[k] = unescape(v);
                    try{
                        paramData[k] = JSON.parse(paramData[k]);
                    } catch (e) {}

                }
            }
        }

        return paramData;
    }

    //删除系统属性
    var cleanDataKey = function(that, type){
        var removeKey = [];
        if(that){
            for (var key in that.attributes) {
                var value = that.attributes[key];
                if(type){
                    if (value.name && value.name.indexOf(type) != -1) {
                        removeKey[removeKey.length] = value.name;
                    }
                } else {
                    if (value.name && value.name.indexOf(prefix) != -1) {
                        var attrType = value.name.replace(prefix, "").split("-")[0];
                        if(plugs.indexOf(attrType) == -1){
                            removeKey[removeKey.length] = value.name;
                        }
                    }
                }

            }
        }
        for (var j = 0; j < removeKey.length; j++) {
            $(that).removeAttr(removeKey[j]);
        }
    }

    /**
     * @param func  本地函数 函数规则 $.xxx(...)
     * @param data  传入数据
     * @param useRetFlag 是否使用自定义返回数据
     * @returns {*}
     */
    var applyLocalFunc = function(func, data, useRetFlag){
        try{
            if(func) {
                var reg = /\$\.\w+\([^\(]*\)/g;
                if(reg.test(func)){
                    var z = func.match(reg);
                    for(var i=0;i< z.length;i++){
                        var newZ = z[i].replace("$.", "").replace("(", ",").replace(")", "");
                        var newZSons = newZ.split(",");
                        var v = window[newZSons[0]];
                        if(!v)
                            return false;
                        var funValues = [];
                        for(var j=0;j<newZSons.length;j++){
                            if(j > 0 && newZSons[j] !== ''){
                                reg = /\{(.+?)\}/g;
                                if(reg.test(newZSons[j])){
                                    var newv = getWindowValue(newZSons[j], data);
                                    if(typeof newv == 'string'){
                                        newv = newv.replace(/'/g, "");
                                    }
                                    funValues[funValues.length] = newv;
                                } else {
                                    funValues[funValues.length] = newZSons[j].replace(/'/g, "");
                                }
                            }
                        }
                        funValues[funValues.length] = data;
                        if(useRetFlag){
                            return v.apply(null, funValues);
                        } else{
                            v.apply(null, funValues);
                            return true;
                        }

                    }

                }
            }
        }catch (e) {
            console.error("函数："+func+" 报错啦 T_T", e);
            return null;
        }

        return false
    }

    //对象值
    var thatDataMap = {};//pool poolSon go
    var thatToData = function (that, type, data) {
        if(!thatDataMap[type]){
            thatDataMap[type] = [];
        }
        var thatDataList =thatDataMap[type];
        var thatToDataFlag = false;
        for(var i=0;i<thatDataList.length;i++){
            var thatData = thatDataList[i];
            if(thatData[0] === that){
                thatToDataFlag = true;
                if(data)
                    thatData[1] = data;
                return thatData[1];
            }
        }

        if(!thatToDataFlag && data){
            var d = [that, data];
            thatDataList[thatDataList.length]=d;
        }
        return null;
    }

    var thatDataRep = function (that, type, repThat) {
        var thatDataList = thatDataByType(type);
        for(var i=0;i<thatDataList.length;i++){
            var thatData = thatDataList[i];
            if(thatData[0] === that){
                thatData[0] = repThat;
            }
        }
    }

    var thatDataByType = function(type){
        if(!thatDataMap[type]){
            return [];
        }
        return thatDataMap[type];
    }

    var thatDataBySet = function(type, data){
        thatDataMap[type] = data;
    }

    var thatDataClean = function (type) {
        thatDataMap[type] = [];
    }

    //初始化插件
    var initPlugs = function(that){
        var keys = ["data-go", "data-scroll"];
        for(var i=0;i<keys.length;i++){
            var key = keys[i];
            var d = $(that).attr(key);
            if(d!=null){
                initPlug(that, key);
            } else {
                if($(that).find("["+key+"]").length>0){
                    $(that).find("["+key+"]").each(function () {
                        initPlug(this, key);
                    });

                }
            }
        }

    }

    //滚动条在Y轴上的滚动距离
    function getScrollTop(){
        var scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0;
        if(document.body){
            bodyScrollTop = document.body.scrollTop;
        }
        if(document.documentElement){
            documentScrollTop = document.documentElement.scrollTop;
        }
        scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;
        return scrollTop;
    }

    //文档的总高度
    function getScrollHeight(){
        var scrollHeight = 0, bodyScrollHeight = 0, documentScrollHeight = 0;
        if(document.body){
            bodyScrollHeight = document.body.scrollHeight;
        }
        if(document.documentElement){
            documentScrollHeight = document.documentElement.scrollHeight;
        }
        scrollHeight = (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight;
        return scrollHeight;
    }
    //浏览器视口的高度
    function getWindowHeight(){
        var windowHeight = 0;
        if(document.compatMode == "CSS1Compat"){
            windowHeight = document.documentElement.clientHeight;
        }else{
            windowHeight = document.body.clientHeight;
        }
        return windowHeight;
    }

    var loadInFlag=false
    var initPlug = function(that, key){
        if(key == 'data-go'){
            var g = $(that).attr(key);
            $(that).attr("onclick", '$.go("'+g+'", this.href);return false;');

        } else if(key == 'data-scroll'){
            $(that).css("text-align", "center");
            scroll = {that:that,allLoadFlag:false,data:{}};
            scroll.url = getInitData($(that).attr("data-scroll"));
            scroll.success = getInitData($(that).attr("data-scroll-success"));
            scroll.emptyHtml = $(that).html();
            var pageData = getInitData($(that).attr("data-scroll-data"));
            if(pageData){
                var data = pageData.split("&");
                for(var i=0;i<data.length;i++){
                    if(data[i]){
                        var k = data[i].split("=")[0];
                        var v = data[i].replace(k+"=", "");
                        v = v.replace(/'/g, "")
                        scroll.data[k] = v;
                    }
                }
            }
            scroll.mobileScroll = function () {
                if(loadInFlag || scroll.allLoadFlag){
                    return;
                }

                if(getScrollTop()/(getScrollHeight() - getWindowHeight()) >= 0.95){ //当滚动到距离底部5%时
                    $(that).html('加载中');

                    sendPageReq();
                }
            }
            sendPageReq();

        }
        cleanDataKey(that, key);
    }

    var scrollcall = function(content){
        if(!content || content.length == 0){
            if(scroll.data.page == 1){
                $(scroll.that).html(scroll.emptyHtml);
            } else {
                $(scroll.that).html('');
            }
            scroll.allLoadFlag = true;
        } else {
            $(scroll.that).html('');
        }
        if(!scroll.data[opt.scroll.page]){
            scroll.data[opt.scroll.page] = 0;
        }
        scroll.data[opt.scroll.page]++;
        loadInFlag = false;
    }

    var sendPageReq = function(){
        loadInFlag = true;
        var pageReq = {};
        $.extend(pageReq, scroll.data);
        if(!pageReq[opt.scroll.page])
            pageReq[opt.scroll.page] = 0;
        if(!pageReq[opt.scroll.size])
            pageReq[opt.scroll.size] = 10;
        for(var i=0;i<opt.scroll.param.length;i++){
            var p = opt.scroll.param[i]
            var cvalue = $.getData("cookie."+p);
            if(cvalue && cvalue != 'undefined')
                pageReq[p] = cvalue;
        }
        $.ajax({url:scroll.url,type:"get",cache:false,data:pageReq,
            success:function(ret){
                var obj = ret;
                if(obj){
                    var content = obj;
                    if(content){
                        var list = applyLocalFunc(scroll.success, content, true);
                        scrollcall.apply(null, [list]);
                    }
                }

            },
            error:function(){
                loadInFlag = false;
            }
        });
    }

    var getInitData = function(attrValue, defaultValue){
        if(attrValue){
            var reg = /\{(.+?)\}/g;
            if(reg.test(attrValue)){
                return $.getData(attrValue);
            } else {
                return attrValue;
            }
            return $.getData(attrValue, true);
        } else {
            attrValue = defaultValue;
        }
        return attrValue;
    }

    //值更改时需要查询的索引
    var getAttrIndex = function(types){
        var index = [];
        for(var type in types){
            var value = types[type];
            try{
                if(type == 'else'){

                } else if(type == 'for' || type == 'each'){
                    value = value.replace(/(\{|\})/g, "");
                    if(value){
                        var attr = value.match(":.*");
                        var splitIndex= attr[0].replace(":", "").trim();
                        splitIndex = splitIndex.split(".")[0];
                        index[index.length] = splitIndex;
                    }
                } else {
                    var reg = /\{[^\{]+\}/g;
                    var regIndexs = value.match(reg)
                    if(regIndexs){
                        for(var i=0;i<regIndexs.length;i++){
                            var regIndex = regIndexs[i].replace(/(\{|\})/g, "");
                            var splitIndexs= regIndex.split(/(=|>|<|!|\?|:|&&|\|\|)/);
                            for(var i2=0;i2<splitIndexs.length;i2++){
                                var splitIndex = splitIndexs[i2].trim();
                                splitIndex = splitIndex.split(".")[0];
                                if(/^\w+(\w|\d|_)*/.test(splitIndex) && index.indexOf(splitIndex) == -1){
                                    index[index.length] = splitIndex;
                                }
                            }

                        }
                    } else {
                        var splitIndexs= value.split(/(=|>|<|!|\?|:|&&|\|\|)/);
                        for(var i2=0;i2<splitIndexs.length;i2++){
                            var splitIndex = splitIndexs[i2].trim();
                            splitIndex = splitIndex.split(".")[0];
                            if(/^\w+(\w|\d|_)*/.test(splitIndex) && index.indexOf(splitIndex) == -1){
                                index[index.length] = splitIndex;
                            }
                        }

                    }
                }
            }catch (e) {
                console.error('data-'+ type+'语法错误 data-'+type +'="'+types[type]+'"');
            }
        }
        if(!index){
            index = [];
        }
        return index;
    }


    var setAttrValue = function(that, poolType, pdata){
        if(!pdata)
            pdata = pageData;
        var p = thatToData(that, poolType);
        if(!p){
            return;
        }
        if((p.types['for'] != null || p.types['each'] != null) && (poolType.indexOf('fragment') == 0 || poolType.indexOf('pool') == 0)){
            for_(that, poolType, pdata);
            return;
        } else if(p.types['elif'] != null || p.types['else'] != null){
            return;
        }
        setAttrValueNotFor(that, poolType, pdata)
    }

    var for_ = function(that, poolType, sonData){
        var valData = {};
        $.extend(valData, sonData);
        var p = thatToData(that, poolType);
        var key = "";
        if(p.types['for'] != null){
            key = p.types['for'];
            for(var j=0;j<p.list.length;j++){
                p.list[j].remove();
            }
            p.list = [];
            p.i = 0;
        } else {
            key = p.types['each'];
        }

        key = key.replace(/(\{|\})/g, "");
        var bes = key.split(":");
        var kName = bes[0].split(",")[0];
        var indexName = bes[0].split(",")[1];

        var list = getWindowValue(bes[1], valData);

        if(list != null && list instanceof Array && list.length>0){
            for(var j=0;j<list.length;j++){

                valData[kName.trim()] = list[j];//取得当前值
                if(indexName){
                    valData[indexName.trim()] = p.i;//取得index
                }
                p.i++;
                var newThat = $(that).clone();
                //如果返回false则不显示
                if(!setAttrValueNotFor(that, poolType, valData)){
                    continue;
                }

                thatDataRep(that, poolType, newThat);
                p.list[p.list.length] = that;
                var poolName = poolType+"_son";
                loadAttrData(that, poolName);
                $(p.placeholder).before(that);
                var hPoolSon = thatDataByType(poolName);
                for(var h=0;h<hPoolSon.length;h++){
                    setAttrValue(hPoolSon[h][0], poolName, valData);
                }
                thatDataClean(poolName);
                that = newThat;
                p.that = newThat;

            }
        } else if(list != null) {
            for(var key in list){
                valData[kName.trim()] = {key:key,value:list[key]};//取得当前值
                if(indexName){
                    valData[indexName.trim()] = p.i;//取得index
                }
                p.i++;
                var newThat = $(that).clone();
                //如果返回false则不显示
                if(!setAttrValueNotFor(that, poolType, valData)){
                    continue;
                }
                thatDataRep(that, poolType, newThat);
                p.list[p.list.length] = that
                var poolName = poolType+"_son";
                loadAttrData(that, poolName);
                $(p.placeholder).before(that);
                var hPoolSon = thatDataByType(poolName);
                for(var h=0;h<hPoolSon.length;h++){
                    setAttrValue(hPoolSon[h][1].that, poolName, valData);
                }
                thatDataClean(poolName);
                that = newThat;
                p.that = newThat;

            }
        } else if(list == null){
            for(var j=0;j<p.list.length;j++){
                p.list[j].remove();
            }
            p.list = [];
            p.i = 0;
        }
        $(placeholderThat).append($(that));
    }

    var setAttrValueNotFor = function (that, poolType, pdata) {
        if(!pdata)
            pdata = pageData;
        var p = thatToData(that, poolType);
        if(!p){
            return true;
        }
        var flag = true;
        for(var type in p.types){
            var key = p.types[type];
            if(type == 'if'){
                flag = setAttrIfValue(that, poolType, pdata);
                var eFlag = flag;
                for(var i=0;i<p.ifs.length;i++){
                    eFlag = setAttrIfValue(p.ifs[i], poolType, pdata, eFlag);
                    if(flag){
                        eFlag = true;
                    }
                    setAttrValueNotFor(p.ifs[i], poolType, pdata);
                }
            } else if(type == 'elif'){

            } else if(type == 'for' || type == 'each'){

            } else {
                var tagName = $(that).prop("tagName").toLowerCase();
                if(type == 'text') {
                    if (tagName == 'textarea') {
                        $(that).val(getWindowValue(key, pdata));
                    } else {
                        $(that).html(getWindowValue(key, pdata));
                    }
                } else if(type == 'checked'){
                    var v = getWindowValue(key, pdata);
                    if(v && v != 'false'){
                        $(that).prop("checked", true);
                    } else {
                        $(that).prop("checked", false);
                    }
                } else{
                    $(that).attr(type, getWindowValue(key, pdata));
                }

            }

        }
        return flag;
    }


    var setAttrIfValue = function (that, poolType, pData, isHide) {
        if(!pData)
            pData = pageData;
        var flag = false;
        var p = thatToData(that, poolType)
        if(!p){
            return flag;
        }
        for(var type in p.types){
            var key = p.types[type];
            var that = p.that;

            if(type == 'if' || type == 'elif'){
                if(isHide){
                    $(placeholderThat).append($(that));
                    flag = true;
                } else {
                    var flag = getWindowValue(key, pData);
                    if(flag){
                        $(p.placeholder).after($(that))
                    } else {
                        $(placeholderThat).append($(that));
                    }
                }
            } else if(type == 'else'){
                if(isHide){
                    $(placeholderThat).append($(that));
                    flag = true;
                } else {
                    $(p.placeholder).after($(that))
                    flag = true;
                }
            }
        }
        return flag;
    }


    var initAttrData = function(that, poolType, pData){
        var p = thatToData(that, poolType);
        if(p){
            return;
        }
        var data = {that:that,placeholder:null,ifs:[],list:[],i:0, types:{}, index:[]};
        for (var i=0;i<that.attributes.length;i++) {
            var key = that.attributes[i].name;
            var value = that.attributes[i].value;
            var reg = new RegExp("^"+prefix);
            if(reg.test(key)){
                var type = key.replace(prefix, "");
                var attrType = type.split("-")[0];
                if(plugs.indexOf(attrType) > -1){
                    continue;
                }
                data.types[type] = value;
            }
        }

        data.index = getAttrIndex(data.types);

        if(data.types['if'] != null || data.types['elif'] != null || data.types['else'] != null
            || data.types['for'] != null || data.types['each'] != null){
            data.placeholder = $("<i style='display:none;'></i>").get(0);
            $(that).before($(data.placeholder));
            if(data.types['for'] != null || data.types['each'] != null){
                $(placeholderThat).append($(that))
            } else if(data.types['if'] != null){
                var ifFlag = true;
                var next = that;
                do {
                    var next = $(next).next().get(0);
                    if($(next).length<=0){
                        ifFlag = false;
                        continue;
                    }
                    var type = $(next).attr(prefix+"elif");
                    if(type == null){
                        type = $(next).attr(prefix+"else");
                    }
                    if(type == null){
                        ifFlag = false;
                        continue;
                    }
                    var index = getAttrIndex([type]);
                    for(var i=0;i<index.length;i++){
                        if(data.index.indexOf(index[i]) == -1){
                            data.index[data.index.length] = index[i];
                        }
                    }

                    loadAttrData(next, poolType);
                    data.ifs[data.ifs.length] = next;
                }while (ifFlag)
            } else if(data.types['elif'] != null || data.types['else'] != null){

            }
        }

        thatToData(that, poolType, data);
        cleanDataKey(that);
        if(poolType =='fragment' || poolType =='pool'){
            setAttrValue(that, poolType, pData);
        } else if(poolType =='plug'){
            setAttrValue(that, poolType, pData);
        }


    }

    var loadAttrData = function(that, poolType, pData){
        if(!pData){
            pData = pageData;
        }
        if(that.attributes){
            for (var i=0;i<that.attributes.length;i++) {
                var key = that.attributes[i].name;
                var reg = new RegExp("^"+prefix);
                if(reg.test(key)){
                    initAttrData(that, poolType, pData);
                    break;
                }
            }
        }
        var p = thatToData(that, poolType);
        if(p){
            if(p.types["for"] != null || p.types["each"] != null){
                return;
            }
        }
        for(var i=0;i<$(that).children().size();i++){
            var t = $(that).children()[i];
            loadAttrData(t, poolType, pData);
        }
    }


    //分解html成title, head, style, body
    var decomposeHtml = function (html) {
        var htmlData = {title:"",body:"", script:[], style:[], scriptHtml:[], styleHtml:[]};
        var titleHtml = html.match(/<title[^>]*>([\s\S]+?)<\/title>/i);
        if(titleHtml)
            htmlData.title = titleHtml[1];
        var bodyHtml = html.match(/<body[^>]*>([\s\S]+?)<\/body>/i);
        htmlData.body = bodyHtml[1];

        var headHtml = html.match(/<head[^>]*>([\s\S]+?)<\/head>/i);
        var script = headHtml[0].match(/<script([\s\S]+?)<\/script>/ig);

        var style = headHtml[0].match(/<style([\s\S]+?)<\/style>/ig);

        if(script){
            for(var i=0;i<script.length;i++){
                htmlData.scriptHtml[htmlData.scriptHtml.length] = script[i];
            }
        }
        if(style){
            for(var i=0;i<style.length;i++){
                htmlData.styleHtml[htmlData.styleHtml.length] = style[i];
            }
        }
        return htmlData;
    }

    //加载外部html页面
    var bodyScript = [];
    var bodyStyle = [];
    var loadHtmlUrl = function (that, url, isBody) {
        if(!that){
            return;
        }
        $.ajax({
            url: url+"?_="+opt.version,
            catch : opt.useCatch,
            dataType: "text",
            success: function (html) {
                var deco = decomposeHtml(html);
                if(that === fragment){
                    initPage = false;
                    $("title").html(deco.title);
                }
                var scriptHtmlBig = "";
                for(var i=0;i<deco.scriptHtml.length;i++){
                    scriptHtmlBig+=deco.scriptHtml[i]+"\n";
                }
                var styleHtmlBig = "";
                for(var i=0;i<deco.styleHtml.length;i++){
                    styleHtmlBig+=deco.styleHtml[i]+"\n";
                }

                var bigLasts = lastLoad(scriptHtmlBig)
                var lastScriptHtmlBig = "";
                if(bigLasts){
                    for(var i=0;i<bigLasts.length;i++){
                        scriptHtmlBig = scriptHtmlBig.replace(bigLasts[i], "");
                        lastScriptHtmlBig+=bigLasts[i]+"\n";
                    }
                }
                var script;
                if(scriptHtmlBig){
                    script = $("<script>"+scriptHtmlBig.replace(/<script.*>/ig, "").replace(/<\/script>/ig, "")+"</script>");
                }
                if(lastScriptHtmlBig){
                    var lastscript = $("<script>"+lastScriptHtmlBig+"</script>");
                }

                var style;
                if(styleHtmlBig){
                    style = $("<style>"+styleHtmlBig.replace(/<style>/ig, "").replace(/<\/style>/ig, "")+"</style>");
                }
                try {
                    if(style)
                        $("head").append(style);
                }catch (e) {console.log(style.get(0), "\n", e)}

                try {
                    if(script)
                        $("head").append(script);
                }catch (e) {console.log("加载script出错\n", script.get(0), "\n", e)}
                try {
                    $(that).html(deco.body);
                }catch (e) {console.log("加载html出错\n",deco.body, "\n", e)}
                try {
                    if(lastscript)
                        $("head").append(lastscript);
                }catch (e) {console.log("加载script出错\n", lastscript.get(0), "\n", e)}
                if(lastscript)
                    lastscript.remove();

                if(isBody){
                    if(script)
                        bodyScript[bodyScript.length] = script;
                    if(style)
                        bodyStyle[bodyStyle.length] = style;

                }
                loadInclude(isBody);
                if(initPage){
                    loadAttrData(that, "pool");
                } else {
                    loadAttrData(that, "fragment");
                }

            },
            error: function () {
            }
        });
        cleanDataKey(that, "data-layout");
    }

    var lastLoad = function (text) {
        var bigLasts = [];
        var shbs = text.split(/\$\(function\s*\(\)\s*{/ig);
        if(shbs){
            for(var i=0;i<shbs.length;i++){
                if(i>0){
                    var shb = shbs[i];
                    var lastHtml = lastLoadText(shb, 0, 0);
                    bigLasts[bigLasts.length]=lastHtml;
                }

            }
        }
        return bigLasts;
    }

    var lastLoadText = function (text, bindex, eindex) {
        if(text){
            var b = text.indexOf("{", bindex);
            var e = text.indexOf("}", eindex);
            if(!b || b==-1 || b >= e){
                return text.substring(0, e);
            } else {
                return lastLoadText(text, b+1, e+1);
            }
        }
    }

    //初始化include
    var loadInclude = function(isBody){
        $("[data-layout-include]").each(function () {
            var that = this;
            var url = $(this).attr("data-layout-include");
            loadHtmlUrl(that, url, isBody);
        });
    }

    var changeUrl = function () {
        if(!thatToData(fragment, "pageNo")){
            pageNo++;
            thatToData(fragment, "pageNo", pageNo);
        }

        $(fragment).html("");
        resetSysData();
        var rootPath = location.pathname.replace(".html", "/");
        var url = rootPath + pageData.search["_"]+".html";
        loadHtmlUrl(fragment, url, true);
        loadAttrData($("body").get(0), "pool");
    }

    var resetSysData = function () {
        pageData.search = {};
        $.extend(pageData.search, urlParam(location.search, /\?|&|#/));
        if(!pageData.search["_"])
            pageData.search["_"] = "index";
        $.extend(pageData.hash, urlParam(location.hash, /\?|&|#/));
        $.extend(pageData.cookie, urlParam(document.cookie, /;/));
        pageData.window.width = document.documentElement.clientWidth || document.body.clientWidth;
        pageData.window.height = document.documentElement.clientHeight || document.body.clientHeight;
        $.setData({search:pageData.search,hash:pageData.hash,cookie:pageData.cookie});
    }

    var main = function(){
        loadInclude(false);
        initPlugs($("body").get(0));
        changeUrl();
        // touchMoveBind();
    }


    $(document).ready(function(){
        fragment = $("[data-layout-fragment='body']").get(0);
        $(fragment).css("animation", "myopacity 1s");
        $(fragment).removeAttr("data-layout-fragment")
        fragmentClone = $(fragment).clone();
        main();

        $("body").bind('DOMNodeInserted', function(e) {
            var that = $(e.target)
            initPlugs(that.get(0));
        });

        $(window).scroll(function () {
            if(scroll && scroll.mobileScroll){
                scroll.mobileScroll();
            }
        })

        if (window.history && window.history.pushState) {
            $(window).on('popstate', function (e) {
                popstate(e)
            });
            goState = true;
        } else {

        }

        // $("body").prepend(touch)

    });

    // var touch = $('<div style="    font-weight: bold;\n' +
    //     '    font-size: 18px;\n' +
    //     '    display: flex;\n' +
    //     '    justify-content: center;\n' +
    //     '    align-items: center;\n' +
    //     '    height: 0px;\n' +
    //     '    position: fixed;\n' +
    //     '    left: 0px;\n' +
    //     '    right: 0px;\n' +
    //     '    z-index: 999;\n' +
    //     '    background: rgb(255, 255, 255);\n' +
    //     '    opacity: 0.9;">下拉刷新</div>').get(0);
    // $(touch).hide();
    //
    // var touchMoveBind = function () {
    //
    //     var startY,
    //         moveY,
    //         isScrollTop=false;
    //     document.addEventListener('touchstart', function (e) {
    //         moveY = 0;
    //         startY = e.touches[0].pageY;
    //         if(getScrollTop()==0){
    //             isScrollTop = true;
    //             $(touch).html("下拉刷新");
    //         }
    //
    //     })
    //     document.addEventListener('touchmove', function (e) {
    //         if(!isScrollTop)return;
    //         moveY = e.touches[0].pageY - startY-20;
    //         if(moveY>0){
    //             $(touch).show();
    //             if (moveY > 80){
    //                 $(touch).html("松开刷新");
    //             } else {
    //                 $(touch).html("下拉刷新");
    //             }
    //             if (moveY > 100) {
    //                 moveY = 100;
    //             }
    //
    //             $(touch).css("height", moveY);
    //         } else {
    //             $(touch).hide();
    //         }
    //     });
    //     document.addEventListener('touchend', function (e) {
    //         $(touch).css("height",0)
    //         if(!isScrollTop)return;
    //         $(touch).html("下拉刷新");
    //         $(touch).hide();
    //         if (moveY > 80) {//下拉
    //             moveY = 0;
    //             go("redirect", location.search);
    //         } else {//上拉
    //
    //         }
    //         isScrollTop = false;
    //     });
    // }


    var pageNo = 0;
    var pageUrlList = [];
    var pageUrlHead = $("<div></div>");
    var pageSwitch = {};
    var fragmentHtml = $("<div></div>");
    var go = function (type, href) {
        if(!goState){//不支持
            if(type == 'navigate'){
                location.href = href;
            } else if(type == 'switch'){
                history.replaceState(null, null, href);
                location.reload();
            } else if(type == 'reLaunch'){
                history.go(-(history.length-1));
            } else if(type == 'redirect'){
                history.replaceState(null, null, href);
                location.reload();
            }
            return;
        }

        if(type == 'navigate'){

            var pageUrlData = {scrollTop:getScrollTop(),data:{},bodyStyle:bodyStyle,bodyScript:bodyScript,fragment:fragment,pageData:pageData,thatList:thatDataByType("fragment")};
            pageUrlData.data.scroll = scroll;
            scroll = null;
            pageUrlList[pageUrlList.length] = pageUrlData;

            for(var i=0;i<bodyScript.length;i++){
                pageUrlHead.append(bodyScript[i]);
            }
            bodyScript = [];
            for(var i=0;i<bodyStyle.length;i++){
                pageUrlHead.append(bodyStyle[i]);
            }
            bodyStyle = [];

            thatDataClean("fragment");
            $(fragment).hide();
            setTimeout(function () {
                var cloneFragment = $(fragmentClone).clone().get(0);
                $(fragment).after(cloneFragment);
                fragmentHtml.append(fragment);
                fragment = cloneFragment;
                pageData = {};
                $.extend(pageData, pageDataInit);
                history.pushState(null, null, href);
                changeUrl();
            }, 1);

        } else if(type == 'redirect'){
            for(var i=0;i<bodyScript.length;i++){
                $(bodyScript[i]).remove();
            }
            bodyScript = [];
            for(var i=0;i<bodyStyle.length;i++){
                $(bodyStyle[i]).remove();
            }
            bodyStyle = [];
            thatDataClean("fragment");
            $(fragment).hide();
            setTimeout(function () {
                var cloneFragment = $(fragmentClone).clone().get(0);
                $(fragment).after(cloneFragment)
                $(fragment).remove();
                fragment = cloneFragment;
                pageData = {};
                $.extend(pageData, pageDataInit);
                history.replaceState(null, null, href);
                changeUrl();
            }, 1);
        } else if(type == 'reLaunch'){
            goState = false;
            history.go(-(history.length-1));
            goState = true;

            var pageUrlDatas = pageUrlList.splice(1, pageUrlList.length);
            for(var i=0;i<pageUrlDatas.length;i++){
                $(pageUrlDatas[i].fragment).remove();
            }
            var pageUrlData = pageUrlList[0];
            setTimeout(function () {
                go("redirect", href);
            }, 100);


        } else if(type == 'switch'){
            var h1 = location.href.split("?")[1];
            var h2 = encodeURI(href).split("?")[1];
            if(h1 == h2){
                return;
            }
            var pageUrlData = pageSwitch[location.search];
            if(!pageUrlData){
                pageUrlData = {data:{},bodyStyle:bodyStyle,bodyScript:bodyScript,fragment:fragment,pageData:pageData,thatList:thatDataByType("fragment")};
                pageUrlData.data.scroll = scroll;
                scroll = null;
                pageSwitch[location.search]= pageUrlData;
            }

            pageUrlData.scrollTop = getScrollTop();
            history.replaceState(null, null, href);
            pageUrlData = pageSwitch[location.search];
            if(!pageUrlData){
                scroll = null;
                for(var i=0;i<bodyScript.length;i++){
                    pageUrlHead.append(bodyScript[i]);
                }
                bodyScript = [];
                for(var i=0;i<bodyStyle.length;i++){
                    pageUrlHead.append(bodyStyle[i]);
                }
                bodyStyle = [];

                thatDataClean("fragment");

                $(fragment).hide();
                setTimeout(function () {
                    var cloneFragment = $(fragmentClone).clone().get(0);
                    $(fragment).after(cloneFragment)
                    fragmentHtml.append(fragment);
                    fragment = cloneFragment;
                    pageData = {};
                    $.extend(pageData, pageDataInit);
                    changeUrl();
                }, 1);
            } else {
                for(var i=0;i<bodyScript.length;i++){
                    pageUrlHead.append(bodyScript[i]);
                }
                for(var i=0;i<bodyStyle.length;i++){
                    pageUrlHead.append(bodyStyle[i]);
                }
                scroll = pageUrlData.data.scroll;
                pageData = pageUrlData.pageData;
                bodyScript = pageUrlData.bodyScript;
                bodyStyle = pageUrlData.bodyStyle;



                thatDataBySet("fragment", pageUrlData.thatList);
                $(fragment).hide();
                setTimeout(function () {
                    $(fragment).after(pageUrlData.fragment);
                    fragmentHtml.append(fragment);
                    fragment = pageUrlData.fragment;
                    try {
                        for(var i=0;i<bodyStyle.length;i++){
                            $("head").append(bodyStyle[i]);
                        }

                        for(var i=0;i<bodyScript.length;i++){
                            var newscript = $(bodyScript[i]).html();
                            $(bodyScript[i]).remove();
                            bodyScript[i] = $("<script>"+newscript+"</script>").get(0);
                            $("head").append(bodyScript[i]);
                        }
                    }catch (e) {}
                    $(fragment).show();
                    resetSysData();
                    window.scrollTo(0, pageUrlData.scrollTop);
                }, 1);


            }

        }
        return;
    }

    var popstate = function(e){
        if(!goState) {
            goState = true;
            return;
        }

        var pageUrlData = pageUrlList.splice(pageUrlList.length-1, pageUrlList.length)[0];
        if(!pageUrlData){
            location.reload();
            return;
        }
        thatDataClean("fragment");
        for(var i=0;i<bodyScript.length;i++){
            pageUrlHead.append(bodyScript[i]);
        }
        for(var i=0;i<bodyStyle.length;i++){
            pageUrlHead.append(bodyStyle[i]);
        }
        scroll = pageUrlData.data.scroll;
        pageData = pageUrlData.pageData;
        bodyScript = pageUrlData.bodyScript;
        bodyStyle = pageUrlData.bodyStyle;



        thatDataBySet("fragment", pageUrlData.thatList);
        $(fragment).hide();
        setTimeout(function () {
            $(fragment).after(pageUrlData.fragment);
            $(fragment).remove();
            fragment = pageUrlData.fragment;
            try {
                for(var i=0;i<bodyStyle.length;i++){
                    $("head").append(bodyStyle[i]);
                }

                for(var i=0;i<bodyScript.length;i++){
                    var newscript = $(bodyScript[i]).html();
                    $(bodyScript[i]).remove();
                    bodyScript[i] = $("<script>"+newscript+"</script>").get(0);
                    $("head").append(bodyScript[i]);
                }
            }catch (e) {}
            $(fragment).show();
            resetSysData();
            window.scrollTo(0, pageUrlData.scrollTop);
        }, 1);


    }

    var moveTarget = function (opt) {
        var moveThat = opt.target;
        var clickThat = opt.clickTarget;
        var isLeftRight = opt.leftRight;
        var call = opt.update;
        var end = opt.end;
        if(!clickThat){
            clickThat = moveThat;
        }
        clickThat.on({
            mousedown: function(e) {
                var os = moveThat.offset();
                var dx = e.pageX-os.left;
                var dy = e.pageY-os.top;
                var thatHeight = moveThat.height();
                var thatWidth = moveThat.width();

                $(document).on('mousemove.drag', function(e2){
                    moveThat.css({"z-index": "1",position:"relative"});
                    moveThat.css({top:e2.pageY-e.pageY});
                    moveThat.css({left:e2.pageX-e.pageX});
                    moveThat.siblings().each(function (i, v) {
                        if(this === moveThat.get(0)){
                            return;
                        }
                        thatHeight = $(v).height();
                        thatWidth = $(v).width();
                        var offLeftStart = $(v).offset().left;
                        var offLeft = offLeftStart+ (thatWidth/2);
                        var offLeftEnd = offLeftStart + thatWidth;

                        var offTopStart = $(v).offset().top;
                        var offTop = offTopStart + (thatHeight/2);
                        var offTopEnd = offTopStart + thatHeight;

                        if(isLeftRight && e2.pageY >=offTopStart &&  e2.pageY <=offTopEnd){
                            if(e2.pageX >= offLeftStart && e2.pageX <= offLeft){
                                $(v).before(moveThat);
                                if(opt.update) opt.update.apply(null);
                            } else if(e2.pageX <= offLeftEnd && e2.pageX >= offLeft){
                                $(v).after(moveThat);
                                if(opt.update) opt.update.apply(null);
                            }
                        } else if(!isLeftRight && e2.pageX >=offLeftStart &&  e2.pageX <=offLeftEnd){
                            if(e2.pageY >= offTopStart && e2.pageY <= offTop){
                                $(v).before(moveThat);
                                if(opt.update) opt.update.apply(null);
                            } else if(e2.pageY <= offTopEnd && e2.pageY >= offTop){
                                $(v).after(moveThat);
                                if(opt.update) opt.update.apply(null);
                            }
                        }
                    });

                    moveThat.offset({top: e2.pageY-dy, left: e2.pageX-dx});
                });

            },
            mouseup: function(e){
                $(document).off('mousemove.drag');
                moveThat.css({"z-index": "0",position:"",left:0, top:0});
                if(opt.end) opt.end.apply();
            }
        });
    }

    $.extend({
        init:function(opts){
            $.extend(opt, opts);
        },
        loadHtml:function(that, data){
            loadAttrData(that, "plug", data);
        },
        setData:function(opt) {
            if(initPage)
                $.extend(pageDataInit, opt);
            $.extend(pageData, opt);
            for(var k in opt){
                var pool = thatDataByType("pool");
                for(var i=0;i<pool.length;i++){
                    var p = pool[i][1];
                    if(p.index.indexOf(k) > -1){
                        setAttrValue(p.that, "pool");
                    }
                }

                pool = thatDataByType("fragment");
                for(var i=0;i<pool.length;i++){
                    var p = pool[i][1];
                    if(p.index.indexOf(k) > -1){
                        setAttrValue(p.that, "fragment");
                    }
                }
            }
        },
        setCookie:function(opt) {
            $.extend(pageData.cookie, opt);
            for(var name in opt){
                var value = JSON.stringify(opt[name]);
                var Days = 30;
                var exp = new Date();
                exp.setTime(exp.getTime() + Days*24*60*60*1000);
                document.cookie = name + "="+ escape (value) +";path=/";
            }
            $.setData({cookie:pageData.cookie});
        },
        setPlug:function(name) {
            if(plugs.indexOf(name) == -1){
                plugs[plugs.length] = name;
            }
        },
        getData:function (key) {
            if(!key){
                return pageData;
            }
            return getWindowValue(key, pageData);
        },

        reloadData:function (key) {
            if(key == 'cookie'){
                var cData = {};
                $.extend(cData, urlParam(document.cookie, /;/));
                $.setData({cookie:cData});
                return;
            }
            var opt = {};
            opt[key] = $.getData(key);
            $.setData(opt);
        },
        cleanDataKey:function(that, key){
            cleanDataKey(that, key)
        },
        go:function (type, href) {
            try{
                go(type, href);
            }catch (e) {
                console.log(e)
            }
            return false;
        },
        goNavigate : function(href){this.go("navigate", href);},
        goSwitch : function(href){this.go("switch", href);},
        goRedirect : function(href){this.go("redirect", href);},
        goReLaunch : function(href){this.go("reLaunch", href);},
        scrollReload:function(reqData) {
            if(scroll){
                if(reqData){
                    $.extend(scroll.data, reqData);
                }
                scroll.data.page = 0;
                scroll.allLoadFlag = false;
                loadInFlag = false;
                sendPageReq();
            }
        },
        scrollReset:function(opt) {
            if(scroll) {
                if (opt) {
                    $.extend(scroll, opt);
                    this.scrollReload({});
                }
            }
        },
        scroll:function(){

        },
        getPageNo:function () {//得到当前页面的编号
            return thatToData(fragment, "pageNo");
        }
    });

    $.fn.extend({
        moveTarget:function(opts){
            this.each(function(){
                var base = {target:$(this),clickThat:null,leftRight:true,update:null,end:null};
                $.extend(base, opts);
                moveTarget(base);
            });
        }
    });

    var getWindowValue = function(key, data){
        var regNumber = /^[0-9]+(\.[0-9]+)?$/;
        //去掉换行
        key = key.replace(/\n\s*/ig, "");
        if(key == "''" || key == null){
            return '';
        }
        var key = key.trim();
        if(key == "+" || key == "-" || key == "*" || key == "/" ){
            return key;
        }
        var value = {};

        var reg = /\$\.\w+\([^\(]*\)/g;
        if(reg.test(key)){
            return applyLocalFunc(key, data, true);
        }
        //{} 取值
        reg = /\{(.+?)\}/g;
        if(reg.test(key)){
            value = key;
            var z = key.match(reg);
            for(var i=0;i<z.length;i++){
                var k = z[i].replace(/^[\{]{1}/, "").replace(/[\}]{1}$/, "");
                var v = getWindowValue(k, data);
                if(z[i] != value){
                    value = value.replace(z[i], v==null?"":v);
                } else {
                    value  = v;
                }
            }
            //布尔
            reg = /\$\.\w+\([^\(]*\)/g;
            if(value == 'true'){
                return true;
            } else if(value == 'false'){
                return false;
            } else if(reg.test(value)){
                return getWindowValue(value, data);
            } else {
                return value;
            }
        }

        //取''值
        if(/^'[^']+'$/.test(key)){
            var key2 =  key.replace(/'/g, "").trim();
            return key2;
        }


        //() 括号运算
        reg = /\(([^\(])+?\)/g;
        if(reg.test(key)){
            value = key;
            var z = key.match(reg);
            var bes = key.split(reg);
            for(var i=0;i<z.length;i++){
                var k = z[i].replace(/^[\(]{1}/, "").replace(/[\)]{1}$/, "");
                var v = getWindowValue(k, data);
                if(v == null){
                    v = "";
                }
                if(z[i] != value){
                    value = value.replace(z[i], "'"+v+"'");
                    value =getWindowValue(value, data);
                } else {
                    value  = v;
                }

            }
            //布尔
            if(value == 'true'){
                value= true;
            } else if(value == 'false'){
                value= false;
            }
            return value;
        }

        //三目运算
        reg = /[?|:]{1}/g
        var z = key.match(reg);
        var bes = key.split(reg);
        if(z && z.length == 2 && z[0] == "?" && z[1] == ":"){

            if(getWindowValue(bes[0], data)){
                return getWindowValue(bes[1], data);
            } else {
                return getWindowValue(bes[2], data);
            }
        }

        //&& ||
        reg = /[&|\|]{2}/g
        z = key.match(reg);
        if(z){
            value = false;
            var bes = key.split(reg);
            for(var i=0;i<bes.length;i++){
                if(i>0){
                    if(z[i-1] == "&&"){
                        value = value && getWindowValue(bes[i], data)
                    } else if(z[i-1] == "||"){
                        value = value || getWindowValue(bes[i], data)
                    }

                } else {
                    value = getWindowValue(bes[i], data);
                }
            }
            return value;
        }


        z = key.match(/[==,===,>,<,>=,<=]{1,3}|[!=]{2}/);
        if(z){
            var be = key.split(z);
            var b = be[0].trim();
            var e = be[1].trim();
            var bValue = getWindowValue(b, data);
            var eValue = getWindowValue(e, data);
            bValue = /^0$/.test(bValue)?"0":bValue;
            eValue = /^0$/.test(eValue)?"0":eValue;

            bValue = bValue==null?'':bValue;
            eValue = eValue==null?'':eValue;

            if(z=="==" && bValue==eValue){
            } else if(z=='===' && bValue===eValue){
            } else if(z=='!=' && bValue!=eValue){
            } else if(regNumber.test(bValue) && regNumber.test(eValue)){
                if(z=='>' && bValue>eValue){
                } else if(z=='<' && bValue<eValue){
                } else if(z=='>=' && bValue>=eValue){
                } else if(z=='<=' && bValue<=eValue){
                } else {
                    return false;
                }
            } else {
                return false;
            }
            return true;
        }


        var stringValues = [];
        reg = /'([^'])+?'/g;
        var z = key.match(reg);
        if(z){
            for(var i=0;i<z.length;i++){
                var k = z[i].replace(/'/g, "");
                stringValues[stringValues.length] = k;
                key = key.replace(z[i], "{"+i+"}")
            }
        }
        //加减乘除
        reg = /[+|\-|\*|\/]{1}/g
        z = key.match(reg);
        if(z){
            var bes = key.split(reg);
            for(var i=0;i<bes.length;i++){
                var v2 = null;
                reg = /\{(\d+?)\}/g;
                if(reg.test(bes[i])) {
                    var k = bes[i].replace(/^[\{]{1}/, "").replace(/[\}]{1}$/, "");
                    v2 = stringValues[k];
                } else {
                    v2 = getWindowValue(bes[i], data);
                }

                v2 = (v2==null?'':v2);

                if(i>0){
                    if(v2 == '' && !isNaN(value)){
                        v2 = 0;
                    } else if(value == '' && !isNaN(v2)){
                        value = 0;
                    }
                    if(z[i-1] == "+") {
                        value = value + v2
                    } else if(z[i-1] == "-"){
                        value = value - v2
                    } else if(z[i-1] == "*"){
                        value = value * v2
                    } else if(z[i-1] == "/"){
                        value = value / v2;
                    }
                } else {
                    value = v2;
                }
            }
            return value;
        }


        //如果是数值直接取出
        if(regNumber.test(key)){
            return parseFloat(key);
        }
        //布尔
        if(key == 'true'){
            return true;
        } else if(key == 'false'){
            return false;
        }
        var value = {};
        if(data){
            $.extend(value, data);
        }

        //如果有!则直接运算成boolean
        if(key.indexOf("!") == 0){
            var newKey = key.replace(/^!/, "");
            var value = getWindowValue(newKey, data);
            if(value){
                return false;
            } else {
                return true;
            }
        }


        var ks = key.trim().split(".");
        for(var i2=0;i2<ks.length;i2++){
            var v2 = ks[i2];
            if(value != null){
                var reg = /\[\d+\]/;
                if(reg.test(v2)){
                    if(value[v2.match(/\w+/)]){
                        value = value[v2.match(/\w+/)][v2.match(/[\d+]/)]
                    } else {
                        value = null;
                    }
                } else {
                    value = value[v2];
                }
            }
        };

        if(Array.isArray(value)){
            return value;
        }

        //如果是数值直接取出
        if(regNumber.test(value)){
            return parseFloat(value);
        }
        return value;
    }

})(jQuery);